package org.micode.libs.wxapp.config;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
import cn.binarywang.wx.miniapp.config.WxMaInMemoryConfig;
import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.micode.libs.wxapp.vo.WxAppConfigVO;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;


@Slf4j
public class WxMaConfiguration {

    private IWxMaPropReader propReader;

    /**
     * 推送微信消息的路由设置
     */
    private Map<String, WxMaMessageRouter> routers = Maps.newConcurrentMap();

    /**
     * 微信服务接口
     */
    private Map<String, WxMaService> maServices = Maps.newConcurrentMap();

    public WxMaConfiguration(IWxMaPropReader propReader) {
        this.propReader = propReader;
    }

    private WxMaService loadOneProperty(String appId) {
        WxAppConfigVO configVO = this.propReader.loadConfigForApp(appId);
        if (null == configVO) {
            log.error("The configuration of wechat applet was not found (appId={}).", appId);
            throw new RuntimeException("The configuration of wechat applet was not found");
        }

        WxMaInMemoryConfig config = new WxMaInMemoryConfig();

        config.setAppid(configVO.getAppId());
        config.setSecret(configVO.getSecret());
        config.setToken(configVO.getToken());
        config.setAesKey(configVO.getAesKey());
        config.setMsgDataFormat(configVO.getMsgDataFormat());

        WxMaService service = new WxMaServiceImpl();
        service.setWxMaConfig(config);

        routers.put(appId, newRouter(service));
        maServices.put(appId, service);

        return service;
    }

    public WxMaService updateMaService(String appId) {
        try {
            return loadOneProperty(appId);
        } catch (Exception e) {
            log.warn("Exception updating WxMaService", e);
            return null;
        }
    }

    public Integer removeWxMaService(List<String> delAppIds) {
        try {
            AtomicInteger retCnt = new AtomicInteger(0);
            delAppIds.forEach(appId -> {
                maServices.remove(appId);
                retCnt.incrementAndGet();
            });
            return retCnt.get();
        } catch (Exception e) {
            log.warn("Exception removing WxMaService", e);
            return null;
        }
    }

    public WxMaService getMaService(String appId) {
        WxMaService wxService = maServices.get(appId);
        if (wxService == null) {
            wxService = loadOneProperty(appId);
        }
        return wxService;
    }

    public WxMaMessageRouter getRouter(String appId) {
        return routers.get(appId);
    }

    /**
     * 处理小程序推送消息的处理器接口
     */
    private WxMaMessageRouter newRouter(WxMaService service) {
        final WxMaMessageRouter router = new WxMaMessageRouter(service);
        router.rule().handler(logHandler).next()
                .rule().async(false).content("template").handler(templateMsgHandler).end()
                .rule().async(false).content("text").handler(textHandler).end()
                .rule().async(false).content("pic").handler(picHandler).end()
                .rule().async(false).content("qrcode").handler(qrcodeHandler).end();
        return router;
    }

    /**
     * 模板处理
     */
    private final WxMaMessageHandler templateMsgHandler =
            (wxMessage, context, service, sessionManager) ->
                    service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder()
                            .templateId("此处更换为自己的模板id")
                            .formId("自己替换可用的formId")
                            .data(Lists.newArrayList(
                                    new WxMaTemplateData("keyword1", "339208499", "#173177")))
                            .toUser(wxMessage.getFromUser())
                            .build());

    /**
     * 收到消息处理
     */
    private final WxMaMessageHandler logHandler =
            (wxMessage, context, service, sessionManager) ->
                    service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder()
                            .content("Received message is: " + wxMessage.toJson())
                            .toUser(wxMessage.getFromUser())
                            .build());

    /**
     * 回复文本消息
     */
    private final WxMaMessageHandler textHandler =
            (wxMessage, context, service, sessionManager) ->
                    service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder()
                            .content("Reply text message")
                            .toUser(wxMessage.getFromUser())
                            .build());

    /**
     * 图片处理
     */
    private final WxMaMessageHandler picHandler =
            (wxMessage, context, service, sessionManager) -> {
                WxMediaUploadResult uploadResult = service.getMediaService()
                        .uploadMedia("image", "png",
                                ClassLoader.getSystemResourceAsStream("tmp.png"));
                service.getMsgService().sendKefuMsg(
                        WxMaKefuMessage
                                .newImageBuilder()
                                .mediaId(uploadResult.getMediaId())
                                .toUser(wxMessage.getFromUser())
                                .build());
            };

    /**
     * 二维码处理
     */
    private final WxMaMessageHandler qrcodeHandler =
            (wxMessage, context, service, sessionManager) -> {
                final File file = service.getQrcodeService().createQrcode("123", 430);
                WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
                service.getMsgService().sendKefuMsg(
                        WxMaKefuMessage
                                .newImageBuilder()
                                .mediaId(uploadResult.getMediaId())
                                .toUser(wxMessage.getFromUser())
                                .build());
            };

}
